package com.hr.leetcode.动态规划;

/**
 * @author 周恒哲
 *
 * @date 2020/06/09
 *
 **/
public class Top5_最长回文子串 {
    //暴力破解法
    public String longestPalindrome(String s) {
        int len=s.length();
        if (len<2) {
            return s;
        }
        int maxLen=1;
        int begin=0;
        //s.charAt(i)每次都会检查数组下标越界，因此先转化成字符数组，这一步非必需
        char[] charArray = s.toCharArray();

        //枚举所有长度严格大于1的子串，charArray[i..j]
        for (int i = 0; i < len-1; i++) {
            for (int j = i+1; j < len; j++) {
                if (j-i+1>maxLen&& validPalindromic(charArray,i,j)){//判断在【i,j】内回文字符串是否相等
                    maxLen=j-i+1;
                    begin=i;
                }
            }
        }
        return s.substring(begin,begin+maxLen);
    }

    private boolean validPalindromic(char[] charArray, int left, int right) {
        while (left<right){
            if (charArray[left]!=charArray[right]){
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
    //动态规划

    /*
    字串   b   a    b   a   b
    下标   0   1    2   3   4

    子串右边界j    0       1        2        3       4(要看全部)
    子串左边界i
              0  true   false     true    false    true
              1         true      false   true     false
              2                   true    false    true
              3                           true     false
              4                                    true
     */
    public String longestPalindrome2(String s) {
        int len = s.length();
        // 特判
        if (len < 2) {
            return s;
        }

        int maxLen = 1;
        int begin = 0;

        // 1. 状态定义
        // dp[i][j] 表示s[i...j] 是否是回文串

        // 2. 初始化
        boolean[][] dp = new boolean[len][len];
        for (int i = 0; i < len; i++) {
            dp[i][i] = true;
        }

        char[] chars = s.toCharArray();
        // 3. 状态转移
        // 注意：先填左下角
        // 填表规则：先一列一列的填写，再一行一行的填，保证左下方的单元格先进行计算
        for (int j = 1; j < len; j++) {
            for (int i = 0; i < j; i++) {
                // 头尾字符不相等，不是回文串
                if (chars[i] != chars[j]) {
                    dp[i][j] = false;
                } else {
                    // 相等的情况下
                    // 考虑头尾去掉以后没有字符剩余，或者剩下一个字符的时候，肯定是回文串
                    if (j - i < 3) {
                        dp[i][j] = true;
                    } else {
                        // 状态转移
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                }

                // 只要dp[i][j] == true 成立，表示s[i...j] 是否是回文串
                // 此时更新记录回文长度和起始位置
                if (dp[i][j] && j - i + 1 > maxLen) {
                    maxLen = j - i + 1;
                    begin = i;
                }
            }
        }
        // 4. 返回值
        return s.substring(begin, begin + maxLen);
    }
}
